const eventManager = require('./eventManager.js');
//固定硬件服务
const MY_DEVICE_SERVICE = {
  serviceId: '0000FFF0-0000-1000-8000-00805F9B34FB',
  readUuid: '0783B03E-8535-B5A0-7140-A304D2495CB8',
  writeUuid: '0783B03E-8535-B5A0-7140-A304D2495CBA',
}
const OTA_DEVICE_SERVICE = {
  serviceId: '02F00000-0000-0000-0000-00000000FE00',
  readUuid: '02F00000-0000-0000-0000-00000000FF02',
  writeUuid: '02F00000-0000-0000-0000-00000000FF01',
}
class BluetoothManager {
  constructor() {
    this.devices = []; // 存储搜索到的设备信息
    this._discoveryStarted = false;//储存搜索状态
    this.connected = false; //储存链接状态
    this.deviceId = ''; //链接设备id
    this.notifyState = 0;//通知状态 0没有 1已打开
  }

  // 初始化蓝牙适配器
  openBluetoothAdapter() {
    console.log('start')
    wx.openBluetoothAdapter({
      success: (res) => {
        console.log('openBluetoothAdapter success', res)
        this.startBluetoothDevicesDiscovery()
      },
      fail: (res) => {
        console.log('openBluetoothAdapter_fail', res)
        if (res.errCode === 10001) {
          wx.onBluetoothAdapterStateChange(function (res) {
            console.log('onBluetoothAdapterStateChange', res)
            if (res.available) {
              this.startBluetoothDevicesDiscovery()
            }
          })
        }
      }
    })
  }

  //开始搜索蓝牙
  startBluetoothDevicesDiscovery() {
    if (this._discoveryStarted) {
      return
    }
    this.devices = []
    this._discoveryStarted = true
    wx.startBluetoothDevicesDiscovery({
      allowDuplicatesKey: true,
      success: (res) => {
        console.log('startBluetoothDevicesDiscovery success', res)
        this.onDeviceFound()
        this.onBLEConnectionStateChange()
      },
    })
  }
  //停止搜索
  stopBluetoothDevicesDiscovery() {
    this.devices = []; // 存储搜索到的设备信息
    this._discoveryStarted = false;//储存搜索状态
    wx.stopBluetoothDevicesDiscovery()
  }
  //链接状态监听
  onBLEConnectionStateChange() {
    wx.onBLEConnectionStateChange(res => {
      // 该方法回调中可以用于处理连接意外断开等异常情况
      this.connected = res.connected
      if(this.connected == false){
        this.devices = []; // 存储搜索到的设备信息
        this._discoveryStarted = false;//储存搜索状态
        this.connected = false; //储存链接状态
        this.deviceId = ''; //链接设备id
      }
      console.log(`链接状态 device ${res.deviceId} state has changed, connected: ${res.connected}`)
      eventManager.emitEvent('onBLEConnectionStateChange', res);
    })
  }
  // 监听设备发现事件并保存设备信息
  onDeviceFound() {
    console.log('起始数：', this.devices)
   
    wx.onBluetoothDeviceFound((res) => {
      res.devices.forEach(device => {
        if (!device.name && !device.localName) {
          return
        }
        console.log('设备对象', device)
        const foundDevices = this.devices
        const idx = this.inArray(foundDevices, 'deviceId', device.deviceId)
        if (idx === -1) {
           // 创建一个新的设备对象并添加到数组
          const newDevice = Object.assign({}, device);
          if(newDevice?.localName){
            newDevice.name = newDevice.localName
          }
          console.log('add', newDevice)
          this.devices.push(newDevice);
        } else {
          const newDevice = Object.assign({}, device);
          if(newDevice?.localName){
            newDevice.name = newDevice.localName
          }
          // 更新已存在设备的信息
          this.devices[idx] = newDevice
        }      
        // callback(this.devices)
       
      })
      // console.log("设备列表", this.devices)
      eventManager.emitEvent('onDeviceFound', this.devices);
    });
  }
  async closeConnection() {
    if (this.connected) {
      const res = await new Promise((resolve, reject) => {
        wx.closeBLEConnection({
          deviceId: this.deviceId,
          success: resolve,
          fail: reject
        });
      });
      return res
    }
    return true
  }
  //创建链接
  async createBLEConnection(deviceId, isClose, callback) {
    //展示弹窗防止多次点击
    wx.showLoading({
      title: '正在链接',
    })
    console.log('链接设备id:' + deviceId)
    if(this.connected && isClose) {
      await new Promise((resolve, reject) => {
        console.log('old', this.deviceId)
        wx.closeBLEConnection({
          deviceId: this.deviceId,
          success: resolve,
          fail: reject
        });
      })
    }
    wx.createBLEConnection({
      deviceId,
      success: async (res) => {
        setTimeout(function () {
          wx.hideLoading()
        }, 1000)
        console.log('链接成功...', res)
        this.connected = true
        this.deviceId = deviceId
        this.setBleMtu(deviceId)
       
        if(this.notifyState == 0){
          wx.onBLECharacteristicValueChange((characteristic) => {
            console.log('回调通知总入口:', characteristic.characteristicId)
            if(characteristic.characteristicId == MY_DEVICE_SERVICE.readUuid){
              eventManager.emitEvent('onBLECharacteristicValueChange', characteristic)
            } 
            if(characteristic.characteristicId == OTA_DEVICE_SERVICE.readUuid){
              eventManager.emitEvent('onBLECharacteristicValueChangeOta', characteristic)
            }     
          })
          this.notifyState = 1
        }
        const services = await this.getBLEDeviceServicesAsync(deviceId)
        console.log(services)
        for (let i = 0; i < services.length; i++) {
          if (services[i].isPrimary) {
            await this.getBLEDeviceCharacteristics(deviceId, services[i].uuid)
          }
        }
        callback(deviceId)
      },
      fail: (res) => {
        wx.hideLoading()
        wx.showToast({
          title: '链接失败',
          icon: 'none',
          duration: 2000
        })
        console.log('链接失败!!', res)
      }
    })
    this.stopBluetoothDevicesDiscovery()
  }
 setBleMtu(deviceId){
  wx.setBLEMTU({
    deviceId: deviceId,
    mtu: 512,
    success: (result) => {},
    fail: (result) => {},
    complete: (res) => {},
  })
 }
  openNotifyBLECharacteristicValueChange(deviceId, serviceId, uuid, callback) {
    wx.notifyBLECharacteristicValueChange({
      deviceId,
      serviceId,
      characteristicId: uuid,
      state: true,
      success: (res) => {
        callback(res)
      },
      fail: (res) => {
        console.log('notifyBLECharacteristicValueChange_fail', res)
      }
    })
  }
  sendCommand(deviceId, serviceId, uuid, buffer, callback) {
    wx.writeBLECharacteristicValue({
      deviceId: deviceId,
      serviceId: serviceId,
      characteristicId: uuid,
      value: buffer,
      success: function (res) {
        // 发送成功后，等待接收数据
        console.log('发送成功...', buffer)
        callback(res)
      },
      fail: (res) => {
        console.log('失败...', res)
      }
    });
  }
  getBLEDeviceServicesAsync(deviceId) {
    return new Promise((resolve, reject) => {
      wx.getBLEDeviceServices({
        deviceId: deviceId,
        success: (res) => {
          resolve(res.services);
        },
        fail: (err) => {
          reject(err);
        }
      });
    });
  }

  getBLEDeviceCharacteristics(deviceId, serviceId) {
    console.log('获取设备serviceId...', deviceId + '->' + serviceId)
    return new Promise((resolve, reject) => {
      wx.getBLEDeviceCharacteristics({
        deviceId,
        serviceId,
        success: async (res) => {
          console.log('getBLEDeviceCharacteristics success', res.characteristics)
          for (let i = 0; i < res.characteristics.length; i++) {
            let item = res.characteristics[i]
            //设备基础服务监听
            if (item.uuid == MY_DEVICE_SERVICE.readUuid) {
              wx.notifyBLECharacteristicValueChange({
                deviceId,
                serviceId,
                characteristicId: MY_DEVICE_SERVICE.readUuid,
                state: true,
                success: (res) => {
                  eventManager.emitEvent('notifyBLECharacteristicOk', res)
                },
                fail: (res) => {
                  console.log('notifyBLECharacteristicValueChange_fail', res)
                }
              })
            }
            //设备ota监听
            if (item.uuid == OTA_DEVICE_SERVICE.readUuid) {
              wx.notifyBLECharacteristicValueChange({
                deviceId,
                serviceId,
                characteristicId: OTA_DEVICE_SERVICE.readUuid,
                state: true,
                success: (res) => {
                  eventManager.emitEvent('notifyBLECharacteristicOtaOk', res)
                },
                fail: (res) => {
                  console.log('notifyBLECharacteristicValueChange_fail', res)
                }
              })
            }
          }
          resolve(res.characteristics)
        },
        fail(res) {
          console.error('getBLEDeviceCharacteristics', res)
          reject(res)
        }
      })
    });

  }

  // 封装一个 Promise 化的 notifyBLECharacteristicValueChange 方法
  async notifyBLECharacteristicValueChangeAsync(deviceId, serviceId, characteristicId, state) {
    return new Promise((resolve, reject) => {
      wx.notifyBLECharacteristicValueChange({
        deviceId: deviceId,
        serviceId: serviceId,
        characteristicId: characteristicId,
        state: state,
        success: (res) => {
          resolve(res);
        },
        fail: (err) => {
          reject(err);
        }
      });
    });
  }
  //断开链接
  closeBLEConnection(deviceId, isOta) {
    wx.closeBLEConnection({
      deviceId: deviceId,
      success: (res) => {
        console.log('断开ok', res)
        if(!isOta){
          this.connected = false
          if(this.connected == false){
            this.devices = []; // 存储搜索到的设备信息
            this._discoveryStarted = false;//储存搜索状态
            this.connected = false; //储存链接状态
            this.deviceId = ''; //链接设备id
          }
        }
        console.log(`链接状态 device ${res.deviceId} state has changed, connected: ${res.connected}`)
        eventManager.emitEvent('onBLEConnectionStateChange', {deviceId:deviceId, connected:false});
      },
    });
  }
  //关闭蓝牙初始化
  closeBluetoothAdapter() {
    wx.closeBluetoothAdapter()
    this._discoveryStarted = false
  }
  inArray(arr, key, val) {
    for (let i = 0; i < arr.length; i++) {
      if (arr[i][key] === val) {
        return i;
      }
    }
    return -1;
  }
}

// 导出单例对象
export default new BluetoothManager();
